package main

import (
	"fmt"
	"runtime"
	"time"
)

type TestTT struct {
	TaskQueue []chan []byte
}

func NewMsgHandle() *TestTT {
	return &TestTT{
		TaskQueue: make([]chan []byte, 200),
	}
}

func main() {
	t := NewMsgHandle()
	t.StartWorkerPool()
	time.Sleep(time.Second * 1)
	var i = 1
	for {
		cc := make([]byte, 1000000)
		t.SendMsgToTaskQueue(cc)
		i++
		time.Sleep(time.Millisecond * 500)
		//if i > 200 {
		//	workerID := counter.nextCount() % 200
		//	close(t.TaskQueue[workerID])
		//}
	}
}

func CheckNumGoroutine() {
	fmt.Println("Goroutine num is *********", runtime.NumGoroutine())
}

// StartWorkerPool 启动worker工作池
func (mh *TestTT) StartWorkerPool() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("err in StartWorkerPool")
			fmt.Println("err = ", err)
		}
	}()
	//遍历需要启动worker的数量，依此启动
	for i := 0; i < 200; i++ {
		//一个worker被启动
		//给当前worker对应的任务队列开辟空间
		mh.TaskQueue[i] = make(chan []byte, 1024)
		//启动当前Worker，阻塞的等待对应的任务队列是否有消息传递进来
		go mh.StartOneWorker(i, mh.TaskQueue[i])
	}
}

// StartOneWorker 启动一个Worker工作流程
func (mh *TestTT) StartOneWorker(workerID int, taskQueue chan []byte) {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("err in startoneworker")
			fmt.Println("err = ", err)
		}
	}()
	fmt.Println("Worker ID = ", workerID, " is started.")
	//不断的等待队列中的消息
	for {
		select {
		//有消息则取出队列的Request，并执行绑定的业务方法
		case <-taskQueue:
			fmt.Println("StartOneWorker workId", workerID, len(taskQueue), cap(taskQueue), *&taskQueue)
			time.Sleep(time.Millisecond * 500)
		}
	}
}

type reqCounter struct {
	count uint32
}

func (counter *reqCounter) nextCount() uint32 {
	counter.count++
	return counter.count
}

// StartOneWorker workId 2 1023 1024 0xc000086008 6602   //SendMsgToTaskQueue 2 1023 1024 0xc000070e10 211402
var counter = &reqCounter{}

// SendMsgToTaskQueue 将消息交给TaskQueue,由worker进行处理
func (mh *TestTT) SendMsgToTaskQueue(request []byte) {
	//轮询的平均分配法则
	//得到需要处理此条连接的workerID
	workerID := counter.nextCount() % 200
	//fmt.Println("Add ConnID=", request.GetConnection().GetConnID()," request msgID=", request.GetMsgID(), "to workerID=", workerID)
	//将请求消息发送给任务队列
	fmt.Println("SendMsgToTaskQueue", workerID, len(mh.TaskQueue[workerID]), cap(mh.TaskQueue[workerID]), *&mh.TaskQueue[workerID])
	mh.TaskQueue[workerID] <- request
}
